package my.tester.com;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
import android.provider.MediaStore.Audio;
import android.util.Log;

public class FallDetectionService extends Service {
	private NotificationManager nm;
	private Timer timer = new Timer();
	private static int counter = 0, incrementby = 1;
	private static boolean isRunning = false;
	private static WakeLock wl;

	ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track
																// of all
																// current
																// registered
																// clients.
	int mValue = 0; // Holds last value set by a client.
	static final int MSG_REGISTER_CLIENT = 1;
	static final int MSG_UNREGISTER_CLIENT = 2;
	static final int MSG_SET_INT_VALUE = 3;
	static final int MSG_SET_STRING_VALUE = 4;
	private static final String TAG = "Fall detected";
	final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target
																		// we
																		// publish
																		// for
																		// clients
																		// to
																		// send
																		// messages
																		// to
																		// IncomingHandler.
	private SensorManager myManager;
	private List<Sensor> sensors;
	private Sensor accSensor;
	private double oldX, oldY, oldZ = 0f;
	private double x2;
	private double y2;
	private Object z2;

	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}

	class IncomingHandler extends Handler { // Handler of incoming messages from
											// clients.
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				break;
			case MSG_SET_INT_VALUE:
				counter = msg.arg1;
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	private void sendMessageToUI(int intvaluetosend) {
		for (int i = mClients.size() - 1; i >= 0; i--) {
			try {
				// Send data as an Integer
				mClients.get(i).send(
						Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend,
								0));

				// Send data as a String
				Bundle b = new Bundle();
				b.putString("Fall ", "detected " + intvaluetosend + " times");
				Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
				msg.setData(b);
				mClients.get(i).send(msg);

			} catch (RemoteException e) {
				// The client is dead. Remove it from the list; we are going
				// through the list from back to front so this is safe to do
				// inside the loop.
				mClients.remove(i);
			}
		}
	}

	@Override
	public void onCreate() {
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		 wl = pm.newWakeLock(
                PowerManager.PARTIAL_WAKE_LOCK
                | PowerManager.ON_AFTER_RELEASE,
                TAG);
		 wl.acquire();
		  if (pm.isScreenOn()
				  == false)
		  { wl = pm.newWakeLock(
		                PowerManager.PARTIAL_WAKE_LOCK
		                | PowerManager.ON_AFTER_RELEASE,
		                TAG);
				 wl.acquire();
		  }
		
		super.onCreate();
		Log.i("Can's Lose My Droid Started", "Application Started");
		showNotification();
		myManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		sensors = myManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
		if (sensors.size() > 0) {
			accSensor = sensors.get(0);
			
			
		}
		timer.scheduleAtFixedRate(new TimerTask() {
			public void run() {
				onTimerTick();
			}
		}, 0, 100L);
		isRunning = true;
	}

	private void showNotification() {
		nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		// In this sample, we'll use the same text for the ticker and the
		// expanded notification
		CharSequence text = getText(R.string.service_started);
		// Set the icon, scrolling text and timestamp
		Notification notification = new Notification(R.drawable.ic_launcher,
				text, System.currentTimeMillis());
		// The PendingIntent to launch our activity if the user selects this
		// notification
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(this, FallDetectionActivity.class), 0);
		// Set the info for the views that show in the notification panel.
		notification.setLatestEventInfo(this, getText(R.string.service_label),
				text, contentIntent);
		// Send the notification.
		// We use a layout id because it is a unique number. We use it later to
		// cancel.
		nm.notify(R.string.service_started, notification);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i("Can't Lose My Droid", "Received start id " + startId + ": " + intent);
		return START_STICKY; // run until explicitly stopped.
	}

	public static boolean isRunning() {
		return isRunning;
	}

	private void onTimerTick() {
		Log.i("TimerTick", "Timer doing work." + counter);
		try {

			myManager.registerListener(mySensorListener, accSensor,
					SensorManager.SENSOR_DELAY_GAME);
			sendMessageToUI(counter);

		} catch (Throwable t) { // you should always ultimately catch all
								// exceptions in timer tasks.
			Log.e("TimerTick", "Timer Tick Failed.", t);
		}

	}

	private final SensorEventListener mySensorListener = new SensorEventListener() {
		public void onSensorChanged(SensorEvent event) {
			
			updateTV(event.values[0], event.values[1], event.values[2]);
		}

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}
	};

	private void updateTV(float x, float y, float z) {
		//counter = -999;
		double thisX = x - oldX * 10;
		double thisY = y - oldY * 10;
		double thisZ = z - oldZ * 10;
		double t;

		// accText.setText("x: " + Math.round(thisX) + ";\n y:" +
		// Math.round(thisY) + ";\n z: " + Math.round(thisZ));
		//
		oldX = x;
		oldY = y;
		oldZ = z;

		x2 = oldX / SensorManager.GRAVITY_EARTH;
		y2 = oldY / SensorManager.GRAVITY_EARTH;
		z2 = oldZ / SensorManager.GRAVITY_EARTH;

		t = Math.sqrt(Math.abs(x2) * Math.abs(x2) + Math.abs(y2) * Math.abs(y2)
				+ Math.abs((Double) z2) * Math.abs((Double) z2));
		
		if (t > 2.5) {
			updateDisplay();
			counter +=1;
			try {
				Uri notification = RingtoneManager
						.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
				Ringtone r = RingtoneManager.getRingtone(
						getApplicationContext(), notification);
				r.play();
			} catch (Exception e) {
			}

			String ns = Context.NOTIFICATION_SERVICE;
			NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

			int icon = R.drawable.ic_launcher; // icon from resources
			CharSequence tickerText = "Fall!!!!!"; // ticker-text
			long when = System.currentTimeMillis(); // notification time
			Context context = getApplicationContext(); // application Context
			CharSequence contentTitle = "My notification"; // message title
			CharSequence contentText = "Fall DETECTED! "; // message text

			Intent notificationIntent = new Intent(this, FallDetectionService.class);
			PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
					notificationIntent, 0);

			// the next two lines initialize the Notification, using the
			// configurations above
			Notification notification = new Notification(icon, tickerText, when);
			notification.setLatestEventInfo(context, contentTitle, contentText,
					contentIntent);
			notification.sound = Uri.withAppendedPath(
					Audio.Media.INTERNAL_CONTENT_URI, "6");
			notification.flags |= Notification.FLAG_INSISTENT;
			notification.flags |= Notification.FLAG_AUTO_CANCEL;

			notification.ledARGB = 0xff00ff00;
			notification.ledOnMS = 300;
			notification.ledOffMS = 1000;

			notification.flags |= Notification.FLAG_SHOW_LIGHTS;

			long[] vibrate = { 0, 100, 200, 300 };
			notification.vibrate = vibrate;

			final int HELLO_ID = 1;

			mNotificationManager.notify(HELLO_ID, notification);
			
			
			
			
			
		}

		// AndroidSensorReaderActivity.timer = new Timer();
		// AndroidSensorReaderActivity.timer.schedule(null, 20*1000);

		// restartDisplay();

	}

	private void updateDisplay() {

		// alarmDisplay.setText(
		// new StringBuilder()
		// // Month is 0 based so add 1
		// .append("Fall Detected!").append("!!!")
		// );

		//counter = 100;

	}

	@Override
	public void onDestroy() {
		
		super.onDestroy();
		if (timer != null) {
			timer.cancel();
		}
		counter = 0;
		myManager.unregisterListener(mySensorListener);
		nm.cancel(R.string.service_started); // Cancel the persistent
												// notification.
		Log.i("Can't Lose My Droid", "Application Stopped.");
		if (wl != null)
		{
		wl.release();
		}
		isRunning = false;
	}
}